package com.wei.czz.framework.common.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wei.czz.common.constant.Constant;
import com.wei.czz.common.dto.common.ChildrenNameValue;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.common.multiDIct.MultiDictEnum;
import com.wei.czz.common.enums.ResultEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.po.UserPo;
import com.wei.czz.common.tool.PageDto;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.common.vo.common.UpdateStatusVo;
import com.wei.czz.common.vo.common.multiDict.MultiDictFormVo;
import com.wei.czz.framework.common.dao.MultiDictDao;
import com.wei.czz.framework.common.entity.MultiDictEntity;
import com.wei.czz.framework.common.service.MultiDictService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wei
 * date: 2023-12-26 11:50:17
 * className: MultiDictServiceImpl
 * version: 1.0
 * description:
 */
@Service("multiDictService")
@AllArgsConstructor
public class MultiDictServiceImpl extends ServiceImpl<MultiDictDao, MultiDictEntity> implements MultiDictService {

    private static final Logger log = LoggerFactory.getLogger(MultiDictServiceImpl.class);

    @Override
    public void saveOrEdit(MultiDictEntity multiDict) {
        Long id = multiDict.getId();
        if (Objects.isNull(id)) {

            int count = baseMapper.insert(multiDict);
            log.info("插入级联字典完成。count={}", count);
        } else {

            int count = baseMapper.updateById(multiDict);
            log.info("修改级联字典完成。count={}", count);
        }
    }

    @Transactional
    @Override
    public void batchSave(List<MultiDictEntity> multiDictList) {
        boolean bool = this.saveBatch(multiDictList);
        log.info("批量插入级联字典完成。bool={}", bool);
    }

    @Override
    public PageDto<MultiDictEntity> getPageList(MultiDictFormVo multiDictFormVo) {
        // mp分页对象
        Page<MultiDictEntity> page = new Page<>(multiDictFormVo.getPage(), multiDictFormVo.getLimit());

        // 如果参数传递的父级主键为空，则默认查询顶级级联字典
        long parentId = Optional.ofNullable(multiDictFormVo.getParentId()).orElse(CommonEnum.ZERO.getLongValue());
        // 如果参数包含检索内容，则只做分页查询
        boolean bool = StringUtils.isNotBlank(multiDictFormVo.getWord());

        LambdaQueryWrapper<MultiDictEntity> multiDictLambdaQueryWrapper = new LambdaQueryWrapper<>();
        multiDictLambdaQueryWrapper.eq(MultiDictEntity::getParentId, parentId)
                .eq(Objects.nonNull(multiDictFormVo.getType()), MultiDictEntity::getType, multiDictFormVo.getType())
                .like(bool, MultiDictEntity::getName, multiDictFormVo.getWord())
                .eq(Objects.nonNull(multiDictFormVo.getDefaultStatus()), MultiDictEntity::getDefaultStatus,
                        multiDictFormVo.getDefaultStatus())
                .eq(Objects.nonNull(multiDictFormVo.getStatus()), MultiDictEntity::getStatus,
                        multiDictFormVo.getStatus())
                .eq(MultiDictEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 设置排序方式
        multiDictLambdaQueryWrapper.orderByAsc(MultiDictEntity::getType, MultiDictEntity::getSort,
                MultiDictEntity::getCreateTime);
        // 分页查询
        baseMapper.selectPage(page, multiDictLambdaQueryWrapper);
        log.info("分页查询级联字典完成。list.size={} totalNum={}", page.getRecords().size(), page.getTotal());

        List<MultiDictEntity> multiDictList = page.getRecords();
        if (multiDictList.isEmpty()) {
            return new PageDto<>(Collections.emptyList(), page.getTotal(), multiDictFormVo.getPage(),
                    multiDictFormVo.getLimit());
        }

        if (bool) {
            log.info("包含检索内容，只做分页查询");
            return new PageDto<>(page);
        }

        /*
            查询子级联字典
         */
        List<MultiDictEntity> childrenMultiDictList = this.batchQueryChildrenMultiDictList(multiDictList,
                multiDictFormVo);
        multiDictList.addAll(childrenMultiDictList);

        return new PageDto<>(page);
    }

    @Override
    public List<MultiDictEntity> getList(List<Long> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            log.info("批量获取级联字典，传递的主键列表为空");
            return Collections.emptyList();
        }
        LambdaQueryWrapper<MultiDictEntity> multiDictLambdaQueryWrapper = new LambdaQueryWrapper<>();
        multiDictLambdaQueryWrapper.in(MultiDictEntity::getId, idList)
                .eq(MultiDictEntity::getDeleteStatus, CommonEnum.ZERO.getLongValue());
        // 查询
        List<MultiDictEntity> multiDictList = baseMapper.selectList(multiDictLambdaQueryWrapper);
        log.info("批量获取级联字典，查询完成。size={}", multiDictList.size());
        return multiDictList;
    }

    @Override
    public List<MultiDictEntity> findList(Integer type, Long parentId) {
        if (ObjectUtils.allNull(type, parentId)) {
            log.info("获取级联字典，传递的类型和父级主键均为空");
            return Collections.emptyList();
        }
        LambdaQueryWrapper<MultiDictEntity> multiDictLambdaQueryWrapper = new LambdaQueryWrapper<>();
        multiDictLambdaQueryWrapper.eq(Objects.nonNull(type), MultiDictEntity::getType, type)
                .eq(Objects.nonNull(parentId), MultiDictEntity::getParentId, parentId)
                .eq(MultiDictEntity::getDeleteStatus, CommonEnum.ZERO.getLongValue());
        // 查询
        List<MultiDictEntity> multiDictList = baseMapper.selectList(multiDictLambdaQueryWrapper);
        log.info("查询级联字典完成。size={}", multiDictList.size());
        return multiDictList;
    }

    @Override
    public List<MultiDictEntity> findList(MultiDictEnum multiDictEnum) {

        LambdaQueryWrapper<MultiDictEntity> multiDictLambdaQueryWrapper = new LambdaQueryWrapper<>();
        multiDictLambdaQueryWrapper.eq(MultiDictEntity::getType, multiDictEnum.getValue())
                .eq(MultiDictEntity::getDeleteStatus, CommonEnum.ZERO.getLongValue());
        // 查询
        List<MultiDictEntity> multiDictList = baseMapper.selectList(multiDictLambdaQueryWrapper);
        log.info("查询级联字典完成。multiDictName={} size={}", multiDictEnum.getName(), multiDictList.size());

        return multiDictList;
    }

    @Override
    public List<MultiDictEntity> findChildrenList(String parentPath) {
        List<MultiDictEntity> multiDictList = baseMapper.selectChildren(parentPath, CommonEnum.ZERO.getValue());
        log.info("查询子、子孙级联字典完成。size={}", multiDictList.size());
        return multiDictList;
    }

    @Override
    public List<MultiDictEntity> findChildrenList(List<Long> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            log.info("获取子、子孙级联字典，传递的主键列表参数为空");
            return Collections.emptyList();
        }
        //
        List<MultiDictEntity> multiDictList = this.getList(idList);
        if (multiDictList.isEmpty()) {
            return Collections.emptyList();
        }
        // 查询子数据
        return this.batchQueryChildrenMultiDictList(multiDictList, new MultiDictFormVo());
    }

    @Override
    public List<MultiDictEntity> findChildrenList(MultiDictEnum multiDictEnum) {

        /*
            获取第一级级联字典
         */
        List<MultiDictEntity> multiDictList = this.findOneLevelList(multiDictEnum);
        if (multiDictList.isEmpty()) {
            return multiDictList;
        }
        MultiDictEntity multiDict = multiDictList.get(0);
        String parentPath = multiDict.getParentPath() + multiDict.getId() + Constant.SPLIT;

        /*
            查询子、子孙级联字典
         */
        multiDictList = baseMapper.selectChildren(parentPath, CommonEnum.ZERO.getValue());
        log.info("查询子、子孙级联字典完成。list.size={}", multiDictList.size());

        return multiDictList;
    }

    @Override
    public <T> List<ChildrenNameValue<T>> getDictTree(Integer type, @NonNull Function<String, T> function) {
        LambdaQueryWrapper<MultiDictEntity> multiDictLambdaQueryWrapper = new LambdaQueryWrapper<>();
        multiDictLambdaQueryWrapper.eq(MultiDictEntity::getType, type)
                .eq(MultiDictEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 查询
        List<MultiDictEntity> multiDictList = baseMapper.selectList(multiDictLambdaQueryWrapper);
        if (multiDictList.isEmpty()) {
            log.info("查询级联字典结果为空");
            return Collections.emptyList();
        }
        List<ChildrenNameValue<T>> result = new ArrayList<>();
        List<ChildrenNameValue<T>> lastOptList = new ArrayList<>();
        Map<String, ChildrenNameValue<T>> map = new HashMap<>();

        for (MultiDictEntity multiDict : multiDictList) {
            ChildrenNameValue<T> childrenNameValue = new ChildrenNameValue<>();
            childrenNameValue.setId(multiDict.getId().toString())
                    .setParentId(multiDict.getParentId().toString())
                    .setSort(multiDict.getSort());
            childrenNameValue.setName(multiDict.getName());
            childrenNameValue.setValue(function.apply(multiDict.getValue()));

            map.put(childrenNameValue.getId(), childrenNameValue);

            ChildrenNameValue<T> parentChildrenNameValue = map.get(childrenNameValue.getParentId());
            if (Objects.isNull(parentChildrenNameValue)) {
                if (CommonEnum.ZERO.getStringValue().equals(childrenNameValue.getParentId())) {
                    result.add(childrenNameValue);
                } else {
                    lastOptList.add(childrenNameValue);
                }
                continue;
            }
            TreeSet<ChildrenNameValue<T>> children = parentChildrenNameValue.getChildren();
            if (Objects.isNull(children)) {
                children = new TreeSet<>();
                parentChildrenNameValue.setChildren(children);
            }
        }
        for (ChildrenNameValue<T> childrenNameValue : lastOptList) {
            ChildrenNameValue<T> parentChildrenNameValue = map.get(childrenNameValue.getParentId());
            if (Objects.isNull(parentChildrenNameValue)) {
                log.info("父级级联字典不存在。{}", childrenNameValue);
                continue;
            }
            TreeSet<ChildrenNameValue<T>> children = parentChildrenNameValue.getChildren();
            if (Objects.isNull(children)) {
                children = new TreeSet<>();
                parentChildrenNameValue.setChildren(children);
            }
        }
        return result.stream().filter(multiDict -> CommonEnum.ZERO.getStringValue().equals(multiDict.getParentId()))
                .map(ChildrenNameValue::getChildren)
                .map(ArrayList::new)
                .findFirst()
                .orElse(new ArrayList<>());
    }

    @Override
    public MultiDictEntity get(Long id) {
        // 查询
        MultiDictEntity multiDict = baseMapper.selectById(id);
        if (Objects.isNull(multiDict)) {
            log.info("级联字典数据不出在。id={}", id);
            throw new CzzException(ResultEnum.ILLEGAL_FAIL.getCode(), "级联字典不存在，请确认");
        }
        if (CommonEnum.ONE.getValue().equals(multiDict.getDeleteStatus())) {
            log.info("级联字典数据已删除。id={}", id);
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "级联字典不存在，请确认");
        }
        return multiDict;
    }

    @Override
    public Integer getNextSort(Long parentId, Integer type) {
        Integer maxSort = baseMapper.selectMaxSort(parentId, type, CommonEnum.ZERO.getValue());
        if (Objects.isNull(maxSort)) {
            maxSort = 0;
        }
        return maxSort + 1;
    }

    @Override
    public String getName(Integer type, String value) {
        LambdaQueryWrapper<MultiDictEntity> multiDictLambdaQueryWrapper = new LambdaQueryWrapper<>();
        multiDictLambdaQueryWrapper.select(MultiDictEntity::getName);
        multiDictLambdaQueryWrapper.eq(MultiDictEntity::getType, type)
                .eq(MultiDictEntity::getValue, value)
                .eq(MultiDictEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 查询
        List<MultiDictEntity> multiDictList = baseMapper.selectList(multiDictLambdaQueryWrapper);
        if (multiDictList.isEmpty()) {
            log.info("级联字典查询结果为空。type={} stringValue={}", type, value);
            return StringUtils.EMPTY;
        }
        return multiDictList.get(0).getName();
    }

    @Override
    public <T> Map<T, String> batchGetName(Integer type, Set<String> stringValueSet, Function<String, T> function) {
        LambdaQueryWrapper<MultiDictEntity> multiDictLambdaQueryWrapper = new LambdaQueryWrapper<>();
        multiDictLambdaQueryWrapper.select(MultiDictEntity::getName, MultiDictEntity::getValue);
        multiDictLambdaQueryWrapper.eq(MultiDictEntity::getType, type)
                .in(MultiDictEntity::getValue, stringValueSet)
                .eq(MultiDictEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 查询
        List<MultiDictEntity> multiDictList = baseMapper.selectList(multiDictLambdaQueryWrapper);
        if (multiDictList.isEmpty()) {
            log.info("级联字典查询结果为空。type={} stringValueSet={}", type, stringValueSet);
            return Collections.emptyMap();
        }
        return multiDictList.stream()
                .collect(Collectors.toMap(
                        multiDict -> function.apply(multiDict.getValue()),
                        MultiDictEntity::getName,
                        (n1, n2) -> n1
                ));
    }

    @Override
    public List<MultiDictEntity> findDirectChildrenList(MultiDictEnum multiDictEnum, List<String> valueList) {
        if (CollectionUtils.isEmpty(valueList)) {
            log.info("查询直接子字典，传入字典值列表为空。dictName={}", multiDictEnum.getName());
            return Collections.emptyList();
        }
        Integer status = CommonEnum.ZERO.getValue();
        Integer deleteStatus = CommonEnum.ZERO.getValue();
        // 查询
        List<MultiDictEntity> multiDictList = baseMapper.selectDirectChildren(multiDictEnum.getValue(), valueList,
                status, deleteStatus);
        log.info("查询直接子级联字典完成。dictName={} params.size={} list.size={}", multiDictEnum.getName(),
                valueList.size(), multiDictList.size());
        return multiDictList;
    }

    @Override
    public List<MultiDictEntity> findOneLevelList(MultiDictEnum multiDictEnum) {
        /*
            获取第一级级联字典
         */
        LambdaQueryWrapper<MultiDictEntity> multiDictLambdaQueryWrapper = new LambdaQueryWrapper<>();
        multiDictLambdaQueryWrapper.eq(MultiDictEntity::getType, multiDictEnum.getValue())
                .eq(MultiDictEntity::getParentId, CommonEnum.ZERO.getLongValue())
                .eq(MultiDictEntity::getDeleteStatus, CommonEnum.ZERO.getLongValue());
        // 查询
        List<MultiDictEntity> multiDictList = baseMapper.selectList(multiDictLambdaQueryWrapper);
        log.info("查询第一级级联字典完成。multiDictName={} list.size={}", multiDictEnum.getName(), multiDictList.size());
        return multiDictList;
    }

    @Transactional
    @Override
    public void batchUpdate(List<MultiDictEntity> updateList) {
        boolean bool = this.updateBatchById(updateList);
        log.info("批量修改级联字典完成。bool={}", bool);
    }

    @Override
    public void updateMultiDictStatus(UpdateStatusVo updateStatusVo) {
        // 获取操作用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        LambdaUpdateWrapper<MultiDictEntity> multiDictLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 设置字段值
        multiDictLambdaUpdateWrapper.set(MultiDictEntity::getStatus, updateStatusVo.getStatus())
                .set(MultiDictEntity::getUpdateTime, date)
                .set(MultiDictEntity::getUpdateUser, userPo.getUsername())
                .set(MultiDictEntity::getUpdateUserId, userPo.getUserId());
        // 匹配
        multiDictLambdaUpdateWrapper.in(MultiDictEntity::getId, updateStatusVo.getIdList());
        // 更新
        int count = baseMapper.update(multiDictLambdaUpdateWrapper);
        log.info("修改级联字典状态完成。count={}", count);
    }

    @Override
    public void delete(List<Long> idList) {
        // 获取操作用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        LambdaUpdateWrapper<MultiDictEntity> multiDictLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        multiDictLambdaUpdateWrapper.set(MultiDictEntity::getDeleteStatus, CommonEnum.ONE.getValue())
                .set(MultiDictEntity::getUpdateTime, date)
                .set(MultiDictEntity::getUpdateUser, userPo.getUsername())
                .set(MultiDictEntity::getUpdateUserId, userPo.getUserId());
        multiDictLambdaUpdateWrapper.in(MultiDictEntity::getId, idList)
                .eq(MultiDictEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 删除
        int count = baseMapper.update(multiDictLambdaUpdateWrapper);
        log.info("删除级联字典完成。count={}", count);
    }

    /**
     * 批量查询子级联字典数据
     * @param multiDictList 级联字典列表
     * @return 子级联字典列表
     */
    private List<MultiDictEntity> batchQueryChildrenMultiDictList(List<MultiDictEntity> multiDictList,
                                                                  MultiDictFormVo multiDictFormVo) {
        LambdaQueryWrapper<MultiDictEntity> multiDictLambdaQueryWrapper = new LambdaQueryWrapper<>();
        multiDictLambdaQueryWrapper.and(_multiDictLambdaQueryWrapper -> {
                    for (MultiDictEntity menu : multiDictList) {
                        String parentPath = menu.getParentPath() + menu.getId() + Constant.SPLIT;
                        _multiDictLambdaQueryWrapper.likeRight(MultiDictEntity::getParentPath, parentPath)
                                .or();
                    }
                })
                .eq(Objects.nonNull(multiDictFormVo.getType()), MultiDictEntity::getType, multiDictFormVo.getType())
                .eq(Objects.nonNull(multiDictFormVo.getDefaultStatus()), MultiDictEntity::getDefaultStatus,
                        multiDictFormVo.getDefaultStatus())
                .eq(Objects.nonNull(multiDictFormVo.getStatus()), MultiDictEntity::getStatus,
                        multiDictFormVo.getStatus())
                .eq(MultiDictEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 查询子菜单
        List<MultiDictEntity> childrenMultiDictList = baseMapper.selectList(multiDictLambdaQueryWrapper);
        log.info("查询子级联字典完成。size={}", childrenMultiDictList.size());
        return childrenMultiDictList;
    }
}